package org.ofbiz.epos.print;

import java.util.*;
import java.io.*;

import org.apache.commons.io.IOUtils;

public class LPWrapper {

    protected String printerName;
    protected Map<String, String> options = new HashMap<String, String>();
    protected String inputFile;
    protected int copies = 1;
    protected boolean suppressMessages;
    protected String stdOut;
    protected String stdErr;

    public static final String MEDIA_SIZE_SLIP = "A4";

    public LPWrapper() {
        
    }

    public LPWrapper setCopies(int copies) {
        this.copies = copies;
        return this;
    }

    public LPWrapper setInputFile(String inputFile) {
        this.inputFile = inputFile;
        return this;
    }

    public LPWrapper setPrinterName(String printerName) {
        this.printerName = printerName;
        return this;
    }

    public LPWrapper setOption(String name, String value) {
        this.options.put(name, value);
        return this;
    }

    public LPWrapper setOption(String name) {
        return setOption(name, null);
    }

    public LPWrapper setMediaSize(String mediaSize) {
        return setOption("media", mediaSize);
    }

    public LPWrapper setFitToPage() {
        return setOption("fit-to-page");
    }

    public LPWrapper setPortrait() {
        this.options.remove("landscape");
        return setOption("portrait");
    }

    public LPWrapper setLandscape() {
        this.options.remove("portrait");
        return setOption("landscape");
    }

    public LPWrapper setNoBanner() {
        return setOption("job-sheets", "none");
    }

    public LPWrapper setSuppressMessages(boolean b) {
        this.suppressMessages = b;
        return this;
    }

    private List<String> createCommandsList() {
        List<String> commands = new ArrayList<String>();
        commands.add("lp");
        commands.add("-d");
        commands.add(printerName);
        commands.add("-n");
        commands.add(Integer.toString(this.copies));
        commands.add("-c");
        
        if (this.suppressMessages) {
            commands.add("-s");
        }

        for (Map.Entry<String, String> option : options.entrySet()) {                
                String c = option.getKey() + (option.getValue() != null ? "=" + option.getValue() : "");

                commands.add("-o");
                commands.add(c);
        }
        commands.add(this.inputFile);
        return commands;
    }

    public String getStdOut() {
        return this.stdOut;
    }

    public String getStdErr() {
        return this.stdErr;
    }

    public String toString() {
        List<String> commands = createCommandsList();
        
        StringBuilder sb = new StringBuilder();
        for (String a : commands) {
            sb.append(a);
            sb.append(" ");
        }
        
        return sb.toString();
    }

    public int execute() throws IOException, InterruptedException {
        List<String> commands = createCommandsList();
        ProcessBuilder builder = new ProcessBuilder(commands);
        Process process = builder.start();
        process.waitFor();
        
        this.stdOut = IOUtils.toString(process.getInputStream());
        this.stdErr = IOUtils.toString(process.getErrorStream());
        
        return process.exitValue();
    }

}